#include "filetransferwindow.h"
#include "ui_filetransferwindow.h"


FileTransferInfo::FileTransferInfo()
{

}

FileTransferInfo::FileTransferInfo(QString fileId, QString sfullPath, QString sbasePath, QString dbasePath,
                                   qint64 flength, bool exists, bool isdownload)
{
    this->fileGuid = fileId;
    this->sourceFullPath = sfullPath;
    this->sourceBasePath = sbasePath;
    this->destBasePath = dbasePath;
    this->fileLength = flength;
    this->isExists = exists;
    this->isDownload = isdownload;
}

FileTransferInfo::~FileTransferInfo()
{

}

bool FileTransferInfo::isEmpty()
{
    return (this->fileGuid.isEmpty() || this->fileGuid.isNull());
}

/*
 * 文件传输窗口
 * */
FileTransferWindow::FileTransferWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::FileTransferWindow)
{
    ui->setupUi(this);

    //初始化文件夹图标
    QFileIconProvider provider;
    this->m_folder = provider.icon(QFileIconProvider::Folder);
    this->m_file = provider.icon(QFileIconProvider::File);

    //初始化右键菜单（服务端）
    this->m_serverMenus = new QMenu(this);
    this->m_serverMenus->addAction(ui->actionSDownload);

    ui->lvServer->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->lvServer, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(slotShowServerContextMenu(QPoint)));

    //初始化右键菜单（本地端）
    this->m_localMenus = new QMenu(this);
    this->m_localMenus->addAction(ui->actionLUpload);

    ui->lvLocal->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->lvLocal, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(slotShowLocalContextMenu(QPoint)));

    this->enableUI(false);
    ui->lvServer->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->lvServer->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->lvLocal->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->lvLocal->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->lvTransfer->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->lvTransfer->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->lvComplete->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->lvComplete->setEditTriggers(QAbstractItemView::NoEditTriggers);

    ui->lvServer->setModel(this->m_modelServer);
    ui->lvLocal->setModel(this->m_modelLocal);
    ui->lvTransfer->setModel(this->m_modelTransfer);
    ui->lvComplete->setModel(this->m_modelComplete);
}

FileTransferWindow::~FileTransferWindow()
{
    delete ui;
    delete this->m_lvtranMutex;
    delete this->m_tranHelperMutex;
}

void FileTransferWindow::connectToServer(ModelServer info)
{
    if(info.serverDest.contains(':'))
    {
        //包含冒号说明是ipv6地址
        this->m_url = "ws://[" + info.serverDest + "]:" + QString::number(info.serverPort);
        this->m_furl= "ws://[" + info.serverDest + "]:" + QString::number(info.serverPort + 1);                //暂定文件传输端口为消息传输端口+1
    }
    else
    {
        //不包含冒号认为是ipv4地址
        this->m_url = "ws://" + info.serverDest + ":" + QString::number(info.serverPort);
        this->m_furl= "ws://" + info.serverDest + ":" + QString::number(info.serverPort + 1);                //暂定文件传输端口为消息传输端口+1
    }

    this->m_userName = info.userName;
    this->m_passWd = info.passWd;

    //初始化websocket
    this->m_whelper = new WSockClientHelper(this);
    connect(m_whelper, SIGNAL(onConnectServer()),
            this, SLOT(slotConnectServer()));
    connect(m_whelper, SIGNAL(onDisconnected()),
            this, SLOT(slotDisconnected()));
    connect(m_whelper, SIGNAL(onError()),
            this, SLOT(slotError()));
    connect(m_whelper, SIGNAL(onReceiveMessage(WSockResponse)),
            this, SLOT(slotOnReceiveMessage(WSockResponse)));
    this->m_whelper->connectToServer(m_url);
}

//转换文件大小
QString FileTransferWindow::convertFileSize(qint64 length)
{
    QString arr[] = {{"B"}, {"KB"}, {"MB"}, {"GB"}, {"TB"}};
    int index = 0;
    while (length >= 1024) {
        length = length/1024;
        index++;
    }
    return QString::number(length).append(arr[index]);
}

//将map转换为json字符串
QString FileTransferWindow::convertMapToJsonString(QMap<QString, QString> map)
{
    QJsonDocument doc;
    QJsonObject obj;
    foreach(QString key, map.keys())
    {
        obj.insert(key, map[key]);
    }
    doc.setObject(obj);

    return QString::fromUtf8(doc.toJson());
}

//启用/禁用界面所有控件
void FileTransferWindow::enableUI(bool enable)
{
    ui->gpServer->setEnabled(enable);
    ui->gpLocal->setEnabled(enable);
    ui->lvTransfer->setEnabled(enable);
}

//记录服务端列宽
void FileTransferWindow::regServerViewColumnSize()
{
    this->m_sw1 = ui->lvServer->columnWidth(0);
    this->m_sw2 = ui->lvServer->columnWidth(1);
    this->m_sw3 = ui->lvServer->columnWidth(2);
}

//列出本地目录
void FileTransferWindow::dirLocal(QString parent)
{
    ui->lblLocalPath->setText(parent);

    QFileInfoList lstFiles;
    if(parent.isNull() || parent.isEmpty())
    {
        //为空时列出所有驱动器
        lstFiles = QDir::drives();
    }
    else
    {
        //列出子文件夹和文件
        QDir dir(parent);
        dir.setFilter(QDir::Dirs | QDir::Files);
        dir.setSorting(QDir::DirsFirst);
        lstFiles = dir.entryInfoList();
    }

    this->m_modelLocal->clear();

    this->m_modelLocal->setColumnCount(3);
    this->m_modelLocal->setHeaderData(0,Qt::Horizontal,"名称");
    this->m_modelLocal->setHeaderData(1,Qt::Horizontal,"类型");
    this->m_modelLocal->setHeaderData(2,Qt::Horizontal,"大小");

    ui->lvLocal->setColumnWidth(0, this->m_lw1);
    ui->lvLocal->setColumnWidth(1, this->m_lw2);
    ui->lvLocal->setColumnWidth(2, this->m_lw3);

    if(lstFiles.isEmpty() || lstFiles.length() <= 0)
        return;

    int row = 0;
    for(int i=0; i<lstFiles.length(); i++){
        QFileInfo fi = lstFiles[i];

        if(fi.fileName() == "." || fi.fileName() == "..")
            continue;

        QStandardItem* qitemM = new QStandardItem(fi.fileName());
        QStandardItem* qitemT = new QStandardItem();
        QStandardItem* qitemS = new QStandardItem();

        //添加数据绑定
        QVariant data;
        data.setValue(fi);
        qitemM->setData(data, Qt::UserRole);

        if(fi.isDir())
        {
            //如果是目录或者驱动器
            QString name = fi.fileName();
            if(parent.isNull() || parent.isEmpty())
            {
                //如果是驱动器，baseName是空的
                name = fi.path();
            }

            qitemM->setText(name);
            qitemM->setIcon(this->m_folder);
            qitemT->setText("文件夹");
        }
        else
        {
            //如果是文件
            qitemM->setText(fi.fileName());
            qitemM->setIcon(this->m_file);
            qitemT->setText("文件");
            qitemS->setText(this->convertFileSize(fi.size()));
        }

        this->m_modelLocal->setItem(row, 0, qitemM);
        this->m_modelLocal->setItem(row, 1, qitemT);
        this->m_modelLocal->setItem(row, 2, qitemS);

        row++;
    }
    //ui->lvLocal->update();
}

//传输文件
void FileTransferWindow::transferFile(FiletransferHelper* helper, FileTransferInfo info)
{
    if(info.isEmpty() == false)
    {
        if(info.isDownload)
        {
            //如果是下载
            QString relationName = info.sourceFullPath.mid(info.sourceBasePath.length());
            if(relationName.startsWith('/') || relationName.startsWith('\\'))
                relationName = relationName.mid(1);

            QString localBasePath = info.destBasePath;
            if(localBasePath.endsWith('/') || localBasePath.endsWith('\\'))
                localBasePath = localBasePath.mid(0, localBasePath.length() - 1);

            QString destFullName = localBasePath + '/' + relationName;

            helper->downloadFile(info.fileGuid, destFullName, info.fileLength);
        }
        else
        {
            //如果是上传
            helper->uploadFile(info.fileGuid, info.sourceFullPath);
        }
    }
    else
        qDebug()<<"文件是空的";
}

//获取下一个要上传或下载的文件
FileTransferInfo FileTransferWindow::getNextTransferFile()
{
    FileTransferInfo res;
    this->m_lvtranMutex->lock();

    if(this->m_modelTransfer->rowCount() > 0)
    {
        for(int i=0; i<this->m_modelTransfer->rowCount(); i++)
        {
            QStandardItem* item = this->m_modelTransfer->item(i, 0);
            FileTransferInfo info = item->data(Qt::UserRole).value<FileTransferInfo>();
            if(info.status == FileTransferInfo::waitToTransfer)
            {
                res = info;
                res.itemProgress = this->m_modelTransfer->item(i, 3);

                //将状态改为正在传输
                info.status = FileTransferInfo::TransferStatus::transfering;
                QVariant ndata;
                ndata.setValue(info);
                item->setData(ndata, Qt::UserRole);

                break;
            }
        }
    }

    this->m_lvtranMutex->unlock();
    return res;
}

//创建一个传输连接
FiletransferHelper *FileTransferWindow::createTransferHelper(QString transferToken)
{
    FiletransferHelper* tran = new FiletransferHelper(this);
    connect(tran, SIGNAL(onTraning(FiletransferHelper*,int)),
            this, SLOT(slotTranProgress(FiletransferHelper*,int)));
    connect(tran, SIGNAL(onTransferComplete(FiletransferHelper*,bool)),
            this, SLOT(slotTranComplete(FiletransferHelper*,bool)));
    tran->createConnection(this->m_furl, transferToken);
    tran->connectToServer();

    return tran;
}

//初始化传输列表
void FileTransferWindow::initTransferView()
{
    this->m_lvtransferInited = true;
    this->m_modelTransfer->setHeaderData(0, Qt::Horizontal, "文件");
    this->m_modelTransfer->setHeaderData(1, Qt::Horizontal, "传输方向");
    this->m_modelTransfer->setHeaderData(2, Qt::Horizontal, "大小");
    this->m_modelTransfer->setHeaderData(3, Qt::Horizontal, "进度");

    ui->lvTransfer->setColumnWidth(0, 800);
    ui->lvTransfer->setColumnWidth(1, 100);
    ui->lvTransfer->setColumnWidth(2, 100);
    ui->lvTransfer->setColumnWidth(3, 100);
}

//添加到传输列表
void FileTransferWindow::addToTransferView(FileTransferInfo info)
{
    QString strDirect = info.isDownload? "下载" : "上传";
    QString strStatus;
    if(info.status == FileTransferInfo::TransferStatus::waitToTransfer && info.isDownload)
        strStatus = "待下载";
    else if(info.status == FileTransferInfo::TransferStatus::waitToTransfer && info.isDownload == false)
        strStatus = "待上传";
    else if(info.status == FileTransferInfo::TransferStatus::transfering)
        strStatus = "下载中";
    else if(info.status == FileTransferInfo::TransferStatus::complete)
        strStatus = "已完成";
    else if(info.status == FileTransferInfo::TransferStatus::error)
        strStatus = "错误";

    //创建模型
    QStandardItem* itemName = new QStandardItem(info.sourceFullPath);
    QStandardItem* itemDirect = new QStandardItem(strDirect);
    QStandardItem* itemSize = new QStandardItem(this->convertFileSize(info.fileLength));
    QStandardItem* itemStatus = new QStandardItem(strStatus);

    QVariant data;
    data.setValue(info);
    itemName->setData(data, Qt::UserRole);

    QList<QStandardItem*> row;
    row.append(itemName);
    row.append(itemDirect);
    row.append(itemSize);
    row.append(itemStatus);

    this->m_modelTransfer->appendRow(row);
}

//添加一行数据到已完成列表
void FileTransferWindow::addToCompleteView(QList<QStandardItem *> item, bool isSuccess)
{
    if(this->m_lvcompleteInited == false)
    {
        //初始化
        this->m_lvcompleteInited = true;
        this->m_modelComplete->setColumnCount(4);
        this->m_modelComplete->setHeaderData(0, Qt::Horizontal, "文件");
        this->m_modelComplete->setHeaderData(1, Qt::Horizontal, "传输方向");
        this->m_modelComplete->setHeaderData(2, Qt::Horizontal, "大小");
        this->m_modelComplete->setHeaderData(3, Qt::Horizontal, "状态");

        ui->lvComplete->setColumnWidth(0, 800);
        ui->lvComplete->setColumnWidth(1, 100);
        ui->lvComplete->setColumnWidth(2, 100);
        ui->lvComplete->setColumnWidth(3, 100);
    }

    FileTransferInfo info = item[0]->data(Qt::UserRole).value<FileTransferInfo>();
    if(isSuccess)
    {
        info.status = FileTransferInfo::TransferStatus::complete;
        item[3]->setText("已完成");
    }
    else
    {
        info.status = FileTransferInfo::TransferStatus::error;
        item[3]->setText("传输错误");
    }

    this->m_modelComplete->appendRow(item);
}

//登录回调
void FileTransferWindow::callbackLogin(WSockResponse response)
{
    this->enableUI(true);

    if(this->m_isInit == false)
    {
        //如果是第一次登录
        this->m_isInit = true;

        //向服务器请求根目录
        this->m_whelper->callApi("/Api/ListDir","");

        //列出本地目录
        this->dirLocal("");
    }
    else
    {
        //如果是断线重连，重新加载当前目录
        this->m_whelper->callApi("/Api/ListDir", this->m_currentSevPath);
    }
}

//服务端列出文件夹/文件回调
void FileTransferWindow::callbackListDir(WSockResponse response)
{
    this->m_modelServer->clear();

    this->m_modelServer->setColumnCount(3);
    this->m_modelServer->setHeaderData(0,Qt::Horizontal,"名称");
    this->m_modelServer->setHeaderData(1,Qt::Horizontal,"类型");
    this->m_modelServer->setHeaderData(2,Qt::Horizontal,"大小");

    ui->lvServer->setColumnWidth(0,this->m_sw1);
    ui->lvServer->setColumnWidth(1,this->m_sw2);
    ui->lvServer->setColumnWidth(2,this->m_sw3);

    if(response.val.isNull() || response.val.isEmpty())
        return;

    QJsonDocument doc = QJsonDocument::fromJson(response.val.toUtf8());
    QJsonObject jobj = doc.object();

    //显示当前目录字符串
    ui->lblSeverPath->setText(jobj["Path"].toString());
    this->m_currentSevPath = jobj["Path"].toString();

    //将当前目录内容添加到listview中
    QJsonArray jarr = jobj["Files"].toArray();
    if(jarr.isEmpty() == false)
    {
        for(int i=0;i<jarr.count();i++)
        {
            QJsonObject jitem = jarr[i].toObject();
            QStandardItem* qitemM = new QStandardItem(jitem["Name"].toString());
            QStandardItem* qitemT = new QStandardItem();
            QStandardItem* qitemS = new QStandardItem();

            //设置数据
            QVariant data;
            data.setValue(jitem);
            qitemM->setData(jitem, Qt::UserRole);

            if(jitem["IsDir"].toBool())
            {
                qitemM->setIcon(this->m_folder);
                qitemT->setText("文件夹");
            }
            else
            {
                qitemM->setIcon(this->m_file);
                qitemT->setText("文件");
                qitemS->setText(FileTransferWindow::convertFileSize(jitem["Size"].toInteger()));
            }
            this->m_modelServer->setItem(i, 0, qitemM);
            this->m_modelServer->setItem(i, 1, qitemT);
            this->m_modelServer->setItem(i, 2, qitemS);
        }
    }
}

//请求下载文件列表回调
void FileTransferWindow::callbackDownloadFiles(WSockResponse response)
{
    //记录当前本地目录，待下载的文件都存放到该目录下
    QString localBasePath = ui->lblLocalPath->text();
    this->enableUI(true);

    QJsonDocument jdoc = QJsonDocument::fromJson(response.val.toUtf8());
    QJsonObject jobj = jdoc.object();
    QJsonArray jfiles;

    //传输任务token
    QString transferToken = jobj["TransferToken"].toString();
    jfiles = jobj["Files"].toArray();

    if(jfiles.isEmpty())
        return;
    if(jfiles.count() <= 0)
        return;

    //服务器基础路径
    QString remoteBasePath = jobj["Path"].toString();

    //传输文件列表
    for(int i=0; i<jfiles.count(); i++)
    {
        QJsonObject jfile = jfiles[i].toObject();

        FileTransferInfo tinfo = FileTransferInfo(jfile["FileGUID"].toString(),
                jfile["FileName"].toString(), remoteBasePath, localBasePath,
                jfile["Size"].toInteger(), jfile["IsExists"].toBool(), true);
        tinfo.transferToken = transferToken;

        //添加
        this->addToTransferView(tinfo);
    }

    //如果tableview还没初始化，则进行初始化
    if(this->m_lvtransferInited == false)
        this->initTransferView();

    //传输文件
    this->m_tranHelperMutex->lock();
    FiletransferHelper* tran = nullptr;

    if(this->m_transferConns.count() < this->m_fcons)
    {
        //如果还未达到最大连接数，直接创建新的连接
        tran = this->createTransferHelper(transferToken);
        this->m_transferConns.append(tran);
    }
    else
    {
        //如果达到了最大连接数，则找出是否有空闲的连接
        for(int i=0; i<this->m_transferConns.count(); i++)
        {
            if(this->m_transferConns[i]->isBusy() == false)
            {
                tran = this->m_transferConns[i];
                tran->resetTransferToken(transferToken);
                break;
            }
        }
    }

    if(tran != nullptr)
    {
        //传输文件
        FileTransferInfo info = this->getNextTransferFile();
        QVariant data;
        data.setValue(info.itemProgress);
        tran->data = data;
        this->transferFile(tran, info);
    }
    this->m_tranHelperMutex->unlock();
}

//请求上传文件列表回调
void FileTransferWindow::callbackUploadFiles(WSockResponse response)
{
    this->enableUI(true);

    QJsonDocument jdoc = QJsonDocument::fromJson(response.val.toUtf8());
    QJsonObject jobj = jdoc.object();

    //传输任务token
    QString transferToken = jobj["TransferToken"].toString();

    if(this->m_waitToUploads.isEmpty())
        return;

    //将传输文件添加到列表
    for(int i=0; i<this->m_waitToUploads.length(); i++)
    {
       this->m_waitToUploads[i].transferToken = transferToken;
       this->addToTransferView(this->m_waitToUploads[i]);
    }

    //如果列表还未初始化，先进行初始化，这个必须放添加到列表代码的后面，否则初始化无效
    if(this->m_lvtransferInited == false)
        this->initTransferView();

    //传输文件
    this->m_tranHelperMutex->lock();
    FiletransferHelper* tran = nullptr;

    if(this->m_transferConns.count() < this->m_fcons)
    {
        //如果还未达到最大连接数，创建新连接
        tran = this->createTransferHelper(transferToken);
        this->m_transferConns.append(tran);
    }
    else
    {
        //如果达到了最大连接数，则找出是否有空闲的连接
        for(int i=0; i<this->m_transferConns.count(); i++)
        {
            if(this->m_transferConns[i]->isBusy() == false)
            {
                tran = this->m_transferConns[i];
                tran->resetTransferToken(transferToken);
                break;
            }
        }
    }

    if(tran != nullptr)
    {
        //传输文件
        FileTransferInfo info = this->getNextTransferFile();
        QVariant data;
        data.setValue(info.itemProgress);
        tran->data = data;
        this->transferFile(tran, info);
    }
    this->m_tranHelperMutex->unlock();
}

//服务器连接成功回调
void FileTransferWindow::slotConnectServer()
{
    //连接成功后调用接口进行认证
    QByteArray bpwd = QCryptographicHash::hash(this->m_passWd.toLatin1(), QCryptographicHash::Md5);
    QString spwd = bpwd.toHex();

    QMap<QString,QString> map;
    map.insert("Username", this->m_userName);
    map.insert("Password", spwd);
    QString p = this->convertMapToJsonString(map);

    this->m_whelper->callApi("/Api/Login", p);
}

//连接断开
void FileTransferWindow::slotDisconnected()
{
    enableUI(false);
    if(QMessageBox::question(this,tr("提示"),tr("连接断开，是否重连？")) == QMessageBox::Ok)
    {
        m_whelper->connectToServer(m_url);
    }
}

//连接错误
void FileTransferWindow::slotError()
{
    enableUI(false);
    QMessageBox::critical(this, tr("错误"),
                          tr("连接错误，正在重连~"));
    m_whelper->connectToServer(m_url);
}

//收到服务器数据
void FileTransferWindow::slotOnReceiveMessage(WSockResponse response)
{
    try {
        if(response.status != 0)
            throw response.err;

        if(response.topic == "/Api/Login")
        {
            //登录
            callbackLogin(response);
        }
        else if(response.topic == "/Api/ListDir")
        {
            //列出文件夹/文件
            this->callbackListDir(response);
        }
        else if(response.topic == "/Api/GetDownloadFiles")
        {
            //请求下载文件列表
            this->callbackDownloadFiles(response);
        }
        else if(response.topic == "/Api/CreateUploadTask")
        {
            //请求上传文件
            this->callbackUploadFiles(response);
        }
    } catch (...) {
        QMessageBox::critical(this, "错误", response.err);
        this->enableUI(true);
    }
}

//显示服务端右键菜单
void FileTransferWindow::slotShowServerContextMenu(QPoint p)
{
    if(ui->lvServer->currentIndex().row()>=0)
    {
        ui->actionSDownload->setEnabled(true);
    }
    else
    {
        ui->actionSDownload->setEnabled(false);
    }
    this->m_serverMenus->exec(QCursor::pos());
}

//显示本地右键菜单
void FileTransferWindow::slotShowLocalContextMenu(QPoint p)
{
    if(ui->lvLocal->currentIndex().row() >= 0)
    {
        ui->actionLUpload->setEnabled(true);
    }
    else
    {
        ui->actionLUpload->setEnabled(false);
    }
    this->m_localMenus->exec(QCursor::pos());
}

void FileTransferWindow::slotTranProgress(FiletransferHelper* helper, int progress)
{
    QVariant data = helper->data;
    QStandardItem* itemProgress = data.value<QStandardItem*>();
    itemProgress->setText(QString::number(progress).append("%"));
}

//一个文件传输完成
void FileTransferWindow::slotTranComplete(FiletransferHelper* helper, bool isSuccess)
{
    //找到对应文件信息，将其状态标记为已完成，并删除后添加到已完成列表
    this->m_lvtranMutex->lock();
    for(int i=0; i<this->m_modelTransfer->rowCount(); i++)
    {
        QStandardItem* item = this->m_modelTransfer->item(i, 0);
        QVariant data = item->data(Qt::UserRole);
        FileTransferInfo info = data.value<FileTransferInfo>();
        if(info.fileGuid == helper->currentFileToken)
        {
            QList<QStandardItem*> row = this->m_modelTransfer->takeRow(i);
            this->addToCompleteView(row, isSuccess);
            break;
        }
    }
    this->m_lvtranMutex->unlock();

    //接下来传输下一个文件
    FileTransferInfo info = this->getNextTransferFile();
    if(info.isEmpty() == false)
    {
        qDebug()<<"transferToken:"<<info.transferToken<<helper->transferToken;
        if(info.transferToken != helper->transferToken)
        {
            //如果这个连接不属于要传输的文件的传输任务，则要重置连接token
            helper->resetTransferToken(info.transferToken);
        }

        QVariant data;
        data.setValue(info.itemProgress);
        helper->data = data;
        this->transferFile(helper, info);
    }
}

//服务端，双击打开下一级
void FileTransferWindow::on_lvServer_doubleClicked(const QModelIndex &index)
{
    //记录当前列宽
    this->regServerViewColumnSize();

    QStandardItem* item = this->m_modelServer->item(index.row(), 0);

    QJsonObject data = item->data(Qt::UserRole).value<QJsonObject>();
    if(data["IsDir"].toBool())
    {
        //如果是目录，打开下一级
        QString spath = item->text();
        this->m_currentSevPath += spath+"/";
        this->m_whelper->callApi("/Api/ListDir",this->m_currentSevPath);
    }
}

//服务端，打开上一级
void FileTransferWindow::on_btnSevUp_clicked()
{
    if(this->m_currentSevPath.length() <= 1)
        return;

    if(this->m_currentSevPath.endsWith('/'))
    {
        //记录当前列宽
        this->regServerViewColumnSize();

        QString fpath = this->m_currentSevPath.mid(0, this->m_currentSevPath.length()-1);
        int index = fpath.lastIndexOf('/');
        if(index > 0)
        {
            fpath = fpath.mid(0, index);
        }
        else
        {
            fpath = "";
        }
        this->m_whelper->callApi("/Api/ListDir",fpath);
    }
}

//本地，双击打开下一级
void FileTransferWindow::on_lvLocal_doubleClicked(const QModelIndex &index)
{
    //找到双击项
    QStandardItem* item = this->m_modelLocal->item(index.row(), 0);
    QFileInfo info = item->data(Qt::UserRole).value<QFileInfo>();

    qDebug()<<"mm"<<info.absoluteFilePath();

    if(info.isDir())
    {
        if(info.isRoot())
        {
            //如果是Windows驱动器
            this->m_currentLocalPath = info.path();
            dirLocal(info.path());
        }
        else if(info.isDir())
        {
            QString strDir = info.absolutePath();
            if(strDir.endsWith('/') == false)
                strDir += '/';

            strDir += info.fileName();
            this->m_currentLocalPath = strDir;
            dirLocal(strDir);
        }
    }
}

//本地目录上一级
void FileTransferWindow::on_btnLocalUp_clicked()
{
    if(this->m_currentLocalPath.isNull() || this->m_currentLocalPath.isEmpty())
        return;

    QDir current = QDir(this->m_currentLocalPath);

    if(current.cdUp())
    {
        this->m_currentLocalPath = current.absolutePath();
        dirLocal(this->m_currentLocalPath);
    }
    else
    {
        this->m_currentLocalPath = "";
        dirLocal(this->m_currentLocalPath);
    }
}

//点击下载菜单
void FileTransferWindow::on_actionSDownload_triggered()
{
    //判断当前本地目录是否可写
    try {
        QString localPath = ui->lblLocalPath->text();
        if(localPath.isNull() || localPath.isEmpty() || localPath=='\\' || localPath=='/')
            throw tr("当前本地路径无法写入文件~");

        QFileInfo linfo = QFileInfo(localPath);
        if(linfo.isWritable() == false)
            throw tr("当前本地路径无法写入文件~");

        //获取选中的文件或目录
        QModelIndexList indexs = ui->lvServer->selectionModel()->selectedIndexes();
        QList<QJsonObject> selectedFiles;

        for(int i=0; i<indexs.length(); i++)
        {
            if(indexs[i].column() != 0)
                continue;

            QStandardItem* item = this->m_modelServer->item(indexs[i].row(), 0);
            QJsonObject info = item->data(Qt::UserRole).value<QJsonObject>();
            selectedFiles.append(info);
        }

        //向服务端请求下载文件列表
        if(selectedFiles.length() <= 0)
            return;

        QJsonDocument jdoc;
        QJsonObject jobj;
        QJsonArray jarr;
        jobj.insert("Path",ui->lblSeverPath->text());

        for(int i=0; i<selectedFiles.length(); i++)
        {
            jarr.append(selectedFiles[i]["Name"].toString());
        }

        jobj.insert("FileNames", jarr);
        jdoc.setObject(jobj);

        this->m_whelper->callApi("/Api/GetDownloadFiles", QString::fromUtf8(jdoc.toJson()));
        this->enableUI(false);
    } catch (QString ex) {
        QMessageBox::critical(this,"错误",ex);
    }
}

//右击上传菜单
void FileTransferWindow::on_actionLUpload_triggered()
{
    //获取当前选中项
    QModelIndexList indexes = ui->lvLocal->selectionModel()->selectedIndexes();

    if(indexes.length() <= 0)
        return;

    QList<QFileInfo> files;

    for(int i=0; i<indexes.length(); i++)
    {
        if(indexes[i].column() != 0)
            continue;

        QStandardItem* item = this->m_modelLocal->item(indexes[i].row(), 0);
        QFileInfo file = item->data(Qt::UserRole).value<QFileInfo>();
        files.append(file);
    }

    //递归获取所有文件和子文件
    QList<QFileInfo> actFiles;
    for(int i=0; i<files.length(); i++)
    {
        QList<QFileInfo> subFiles = FiletransferHelper::recursionFiles(files[i], true);
        if(subFiles.isEmpty() == false)
            actFiles.append(subFiles);
    }

    if(actFiles.isEmpty())
        return;

    //将文件的名称转换为本地绝对路径和相对路径，相对路径上传给服务器，绝对路径自己保留，用于读取文件数据
    QString localBasePath = ui->lblLocalPath->text();
    localBasePath = localBasePath.replace('\\','/');
    QString remoteBasePath = ui->lblSeverPath->text();
    remoteBasePath = remoteBasePath.replace('\\', '/');

    QList<FileTransferInfo> tranFiles;
    for(int i=0; i<actFiles.length(); i++)
    {
        QString absoluteName = actFiles[i].absoluteFilePath().replace('\\','/');
        QString relativeName = absoluteName.mid(localBasePath.length());
        FileTransferInfo info = FileTransferInfo(QUuid::createUuid().toString(QUuid::WithoutBraces),
                                                 absoluteName, relativeName, remoteBasePath,
                                                 actFiles[i].size(), true, false);
        tranFiles.append(info);
    }

    this->m_waitToUploads = tranFiles;

    //创建json参数，向服务器申请需要上传的文件列表
    QJsonDocument jdoc;
    QJsonObject jobj;
    QJsonArray jarr;

    jobj.insert("Path", remoteBasePath);
    for(int i=0; i<this->m_waitToUploads.length(); i++)
    {
        QJsonObject fileObj;
        fileObj.insert("FileGUID", this->m_waitToUploads[i].fileGuid);
        fileObj.insert("File",this->m_waitToUploads[i].sourceBasePath);
        jarr.append(fileObj);
    }

    jobj.insert("Files", jarr);
    jdoc.setObject(jobj);

    this->m_whelper->callApi("/Api/CreateUploadTask", QString::fromUtf8(jdoc.toJson()));
    this->enableUI(false);
}

//刷新服务器目录
void FileTransferWindow::on_btnSevRefresh_clicked()
{
    QString path = ui->lblSeverPath->text();
    this->m_whelper->callApi("/Api/ListDir", path);
}

//刷新本地目录
void FileTransferWindow::on_btnLocalRefresh_clicked()
{
    QString path = ui->lblLocalPath->text();
    this->dirLocal(path);
}

